{{#if (or (neq apiEntity.entity.storage "NONE")(apiEntity.entity.virtualMulINHDE))}}
package {{packageName}}.{{apis}}.rest;

import java.util.*;
{{#if entity.hasBigDecimal}}
import java.math.BigDecimal;
{{/if}}
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.HttpStatus;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.ObjectUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.validation.annotation.Validated;
import io.swagger.annotations.ApiOperation;
import java.util.stream.IntStream;
import cn.ibizlab.util.domain.ImportResult;
import cn.ibizlab.util.domain.RequestWrapper;
import cn.ibizlab.util.domain.ResponseWrapper;
import cn.ibizlab.util.enums.CheckKeyStatus;
import {{packageName}}.{{apis}}.dto.*;
import {{packageName}}.{{apis}}.mapping.*;
import {{packageName}}.core.{{apiEntity.entity.module}}.domain.{{apiEntity.entity.domainClassName}};
import {{packageName}}.core.{{apiEntity.entity.module}}.service.{{apiEntity.entity.codeName}}Service;
import {{packageName}}.core.{{apiEntity.entity.module}}.filter.{{apiEntity.entity.codeName}}SearchContext;
{{#if apiEntity.entity.lastModifyField}}
import cn.ibizlab.util.annotation.VersionCheck;
{{/if}}
import reactor.core.publisher.Mono;

/**
 * 实体[{{apiEntity.codeName}}] rest实现
 *
 * @author generator
 */
@Slf4j
public abstract class Abstract{{apiEntity.codeName}}Resource {

    @Autowired
    public {{apiEntity.entity.codeName}}Service {{camelCase apiEntity.entity.codeName}}Service;

{{#each apiEntity.dtos}}
    {{#or (eq type "DEFAULT")(eq type "DEFILTER")}}
    @Autowired
    @Lazy
    public {{codeName}}Mapping {{camelCase codeName}}Mapping;

    {{/or}}
{{/each}}
{{#each apiEntity.methods}}
    {{#unless disabled}}
    {{#neq name "Select"}}
        {{#if wrapperParam}}
            {{#eq methodType "DEACTION"}}
    /**
    * {{apiName}} {{tags}}
    * {{#if psDEAction}}{{psDEAction.memo}}{{/if}}{{#if psDEDataSet}}{{psDEDataSet.memo}}{{/if}}
    *
    {{#each pathVariables}}
    * @param {{camelCase name}} {{camelCase name}}
    {{/each}}
    {{#if body}}
    * @param {{inParamName}} {{inParamName}}
    {{/if}}
    * @return Mono<ResponseEntity<{{outParam}}>>
    */
    @ApiOperation(value = "{{apiName}}", tags = {"{{tags}}" },  notes = "{{notes}} {{#if psDEAction}}{{replaceWrap psDEAction.memo}}{{/if}}{{#if psDEDataSet}}{{replaceWrap psDEDataSet.memo}}{{/if}}")
    {{#if permission}}
    @{{permission.ano}}("{{permission.cond4}}")
    {{/if}}
    {{#eq name "Update"}}
        {{#if apiEntity.entity.lastModifyField}}
    @VersionCheck(entity = "{{lowerCase apiEntity.entity.codeName}}" , versionfield = "{{camelCase apiEntity.entity.lastModifyField.codeName}}")
        {{/if}}
    {{/eq}}
    {{!嵌套行为}}
    @{{pascalCase requestMethod}}Mapping("{{requestPath2}}")
    public Mono<ResponseEntity<{{wrapperOutParam}}>>{{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}
            ({{#each pathVariables}}{{#unless @first}}, {{/unless}}@PathVariable("{{camelCase name}}") {{type.java}} {{camelCase name}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}{{#neq requestMethod 'GET'}}@Validated @RequestBody {{else}}@SpringQueryMap {{/neq}}{{replace wrapperBody "SearchContext" "FilterDTO"}}{{/if}}) {
    {{!嵌套行为路径参数批操作,拆分id循环调用子，如：parent /get/id1;id2 -> get(id) }}
    {{#if needSplitRequestPathId}}
        ResponseWrapper<{{outParam}}> rt = new ResponseWrapper<>();
        if ({{inParamName}}.isArray()) {
            {{apiEntity.entity.keyField.type.java}} [] ids = {{camelCase apiEntity.entity.keyField.codeName}}.split(";");
            IntStream.range(0, ids.length).forEach(i -> rt.add({{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}({{#each pathVariables}}{{#unless @first}}, {{/unless}}{{#if (eq apiEntity.entity.keyField.codeName name)}}ids[i]{{else}}{{camelCase name}}{{/if}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}{{inParamName}}.getList().get(i){{/if}})));
        }
        else
            rt.set({{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}({{#each pathVariables}}{{#unless @first}}, {{/unless}}{{camelCase name}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}{{inParamName}}.getDto(){{/if}}));
        return Mono.just(ResponseEntity.status(HttpStatus.OK).body(rt));
    {{else}}
        {{!嵌套行为路径参数单数据操作 /parent/id -> get(id) }}
        ResponseWrapper<{{outParam}}> rt = new ResponseWrapper<>();
        if ({{inParamName}}.isArray())
            {{inParamName}}.getList().forEach(item -> rt.add({{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}({{#each pathVariables}}{{#unless @first}}, {{/unless}}{{camelCase name}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}item{{/if}})));
        else
            rt.set({{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}({{#each pathVariables}}{{#unless @first}}, {{/unless}}{{camelCase name}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}{{inParamName}}.getDto(){{/if}}));
        return Mono.just(ResponseEntity.status(HttpStatus.OK).body(rt));
    {{/if}}
    }

    /**
    * {{apiName}} {{tags}}
    * {{#if psDEAction}}{{psDEAction.memo}}{{/if}}{{#if psDEDataSet}}{{psDEDataSet.memo}}{{/if}}
    *
    {{#each pathVariables}}
    * @param {{camelCase name}} {{camelCase name}}
    {{/each}}
    {{#if body}}
    * @param {{inParamName}} {{inParamName}}
    {{/if}}
    * @return ResponseEntity<{{outParam}}>
    */   
    {{!标准行为}}
    public {{outParam}} {{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}
            ({{#each pathVariables}}{{#unless @first}}, {{/unless}}{{type.java}} {{camelCase name}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}{{replace body "SearchContext" "FilterDTO"}}{{/if}}) {
        {{#if needDto2Domain}}
        {{inParam2}} {{inParamName2}} = {{camelCase apiMethodInputDTO.codeName}}Mapping.toDomain({{inParamName}});
            {{#if listIn}}
                {{#if pathVariables}}
        {{inParamName2}}.forEach(item -> {
                {{#each pathVariables}}{{#if @last}}
            item.set{{pascalCase name}}({{camelCase name}});
                {{/if}}{{/each}}
        });
                {{/if}}
            {{else}}
                {{#each pathVariables}}{{#if @last}}
        {{inParamName2}}.set{{pascalCase name}}({{camelCase name}});
                {{/if}}{{/each}}
            {{/if}}
        {{/if}}
        {{#if booleanReturn}}
        {{camelCase apiEntity.entity.codeName}}Service.{{camelCase name}}({{inParamName2}});
        {{outParam2}} rt = {{inParamName2}};
        {{else}}
        {{outParam2}} rt = {{camelCase apiEntity.entity.codeName}}Service.{{camelCase name}}({{inParamName2}});
        {{/if}}
        {{#if needDomain2Dto}}
        return {{camelCase apiMethodReturnDTO.codeName}}Mapping.toDto(rt);
        {{else}}
        return rt;
        {{/if}}
    }

            {{/eq}}
        {{/if}}
    {{/neq}}
    {{/unless}}
{{/each}}

{{#each apiEntity.methods}}
{{#unless disabled}}
{{#neq name "Select"}}
    {{#unless wrapperParam}}
    /**
    * {{apiName}} {{tags}}
    * {{#if psDEAction}}{{psDEAction.memo}}{{/if}}{{#if psDEDataSet}}{{psDEDataSet.memo}}{{/if}}
    *
    {{#each pathVariables}}
    * @param {{camelCase name}} {{camelCase name}}
    {{/each}}
    {{#if body}}
    * @param {{inParamName}} {{inParamName}}
    {{/if}}
    * @return Mono<ResponseEntity<{{outParam}}>>
    */
    @ApiOperation(value = "{{apiName}}", tags = {"{{tags}}" },  notes = "{{notes}} {{#if psDEAction}}{{replaceWrap psDEAction.memo}}{{/if}}{{#if psDEDataSet}}{{replaceWrap psDEDataSet.memo}}{{/if}}")
    {{#if permission}}
    @{{permission.ano}}("{{permission.cond4}}")
    {{/if}}
    {{#eq methodType "DEACTION"}}
        {{#eq name "Update"}}
            {{#if apiEntity.entity.lastModifyField}}
    @VersionCheck(entity = "{{lowerCase apiEntity.entity.codeName}}" , versionfield = "{{camelCase apiEntity.entity.lastModifyField.codeName}}")
            {{/if}}
        {{/eq}}
    {{/eq}}
    @{{pascalCase requestMethod}}Mapping("{{requestPath2}}")
    public Mono<ResponseEntity<{{#if (or (eq codeName "CheckKey")(eq codeName "check_key"))}}CheckKeyStatus{{else}}{{outParam}}{{/if}}>> {{camelCase name}}{{#each pathVariables}}{{#if @first}}By{{else}}And{{/if}}{{pascalCase name}}{{/each}}
            ({{#each pathVariables}}{{#unless @first}}, {{/unless}}@PathVariable("{{camelCase name}}") {{type.java}} {{camelCase name}}{{/each}}{{#if body}}{{#if pathVariables}}, {{/if}}{{#neq requestMethod 'GET'}}@Validated @RequestBody {{else}}@SpringQueryMap {{/neq}}{{replace body "SearchContext" "FilterDTO"}}{{/if}}) {
    {{!行为}}
    {{#eq methodType "DEACTION"}}
        {{#if needDto2Domain}}
        {{inParam2}} {{inParamName2}} = {{camelCase apiMethodInputDTO.codeName}}Mapping.toDomain({{inParamName}});
            {{#if listIn}}
                {{#if pathVariables}}
        {{inParamName2}}.forEach(item -> {
                {{#each pathVariables}}{{#if @last}}
            item.set{{pascalCase name}}({{camelCase name}});
                {{/if}}{{/each}}
        });
                {{/if}}
            {{else}}
                {{#each pathVariables}}{{#if @last}}
        {{inParamName2}}.set{{pascalCase name}}({{camelCase name}});
                {{/if}}{{/each}}
            {{/if}}
        {{/if}}
        {{#if booleanReturn}}
        {{camelCase apiEntity.entity.codeName}}Service.{{camelCase name}}({{inParamName2}});
        {{outParam2}} rt = {{inParamName2}};
        {{else}}
        {{#if (or (eq codeName "CheckKey")(eq codeName "check_key"))}}CheckKeyStatus{{else}}{{outParam2}}{{/if}} rt = {{camelCase apiEntity.entity.codeName}}Service.{{camelCase name}}({{inParamName2}});
        {{/if}}
        {{#if needDomain2Dto}}
        return Mono.just(ResponseEntity.status(HttpStatus.OK).body({{camelCase apiMethodReturnDTO.codeName}}Mapping.toDto(rt)));
        {{else}}
        return Mono.just(ResponseEntity.status(HttpStatus.OK).body(rt));
        {{/if}}
    {{/eq}}
    {{!数据集}}
    {{#eq methodType "FETCH"}}
        {{#each pathVariables}}
            {{#if @last}}
        {{inParamName}}.set{{pascalCase name}}EQ({{camelCase name}});
            {{/if}}
        {{/each}}
        {{apiEntity.entity.codeName}}SearchContext context = {{camelCase apiEntity.codeName}}FilterDtoMapping.toDomain({{inParamName}});
        Page<{{apiEntity.entity.domainClassName}}> domains = {{camelCase apiEntity.entity.codeName}}Service.fetch{{pascalCase pSDEDataSet.codeName}}(context) ;
        {{outParam}} list = {{camelCase apiMethodReturnDTO.codeName}}Mapping.toDto(domains.getContent());
            return Mono.just(ResponseEntity.status(HttpStatus.OK)
            .header("x-page", String.valueOf(context.getPageable().getPageNumber()))
            .header("x-per-page", String.valueOf(context.getPageable().getPageSize()))
            .header("x-total", String.valueOf(domains.getTotalElements()))
            .body(list));
    {{/eq}}
    }

{{/unless}}
{{/neq}}
{{/unless}}
{{/each}}

{{#each apiEntity.methods}}
{{#unless disabled}}
{{#unless parentApiEntities}}
    {{#eq name "Create"}}
    /**
    * 批量新建{{apiEntity.entity.logicName}}
    * @param dtos
    * @return Mono<ResponseEntity<Boolean>>
    */
    @PreAuthorize("hasAnyAuthority('ROLE_SUPERADMIN','{{projectName}}-{{apiEntity.entity.codeName}}-Create-all')")
    @ApiOperation(value = "批量新建{{apiEntity.entity.logicName}}", tags = {"{{apiEntity.entity.logicName}}" },  notes = "批量新建{{apiEntity.entity.logicName}}")
	@{{pascalCase requestMethod}}Mapping("{{pluralize apiEntity.opt.codeName}}/{{#if opt.codeName}}{{lowerCase opt.codeName}}{{/if}}batch")
    public Mono<ResponseEntity<Boolean>> createBatch(@RequestBody List<{{apiEntity.defaultDto.codeName}}> dtos) {
        {{camelCase apiEntity.entity.codeName}}Service.create({{camelCase apiEntity.defaultDto.codeName}}Mapping.toDomain(dtos));
        return  Mono.just(ResponseEntity.status(HttpStatus.OK).body(true));
    }

    {{/eq}}
    {{#eq name "Update"}}
    /**
    * 批量更新{{apiEntity.entity.logicName}}
    * @param dtos
    * @return Mono<ResponseEntity<Boolean>>
    */
    @PreAuthorize("hasAnyAuthority('ROLE_SUPERADMIN','{{projectName}}-{{apiEntity.entity.codeName}}-Update-all')")
    @ApiOperation(value = "批量更新{{apiEntity.entity.logicName}}", tags = {"{{apiEntity.entity.logicName}}" },  notes = "批量更新{{apiEntity.entity.logicName}}")
	@{{pascalCase requestMethod}}Mapping("{{pluralize apiEntity.opt.codeName}}/{{#if opt.codeName}}{{lowerCase opt.codeName}}{{/if}}batch")
    public Mono<ResponseEntity<Boolean>> updateBatch(@RequestBody List<{{apiEntity.defaultDto.codeName}}> dtos) {
        {{camelCase apiEntity.entity.codeName}}Service.update({{camelCase apiEntity.defaultDto.codeName}}Mapping.toDomain(dtos));
        return  Mono.just(ResponseEntity.status(HttpStatus.OK).body(true));
    }

    {{/eq}}
    {{#eq name "Save"}}
    /**
    * 批量保存{{apiEntity.entity.logicName}}
    * @param dtos
    * @return Mono<ResponseEntity<Boolean>>
    */
    @PreAuthorize("hasAnyAuthority('ROLE_SUPERADMIN','{{projectName}}-{{apiEntity.entity.codeName}}-Save-all')")
    @ApiOperation(value = "批量保存{{apiEntity.entity.logicName}}", tags = {"{{apiEntity.entity.logicName}}" },  notes = "批量保存{{apiEntity.entity.logicName}}")
	@PostMapping("{{pluralize apiEntity.opt.codeName}}/savebatch")
    public Mono<ResponseEntity<Boolean>> saveBatch(@RequestBody List<{{apiEntity.defaultDto.codeName}}> dtos) {
        {{camelCase apiEntity.entity.codeName}}Service.save({{camelCase apiEntity.defaultDto.codeName}}Mapping.toDomain(dtos));
        return  Mono.just(ResponseEntity.status(HttpStatus.OK).body(true));
    }

    {{/eq}}
    {{#eq name "Save"}}
    /**
    * 批量导入{{apiEntity.entity.logicName}}
    * @param config 导入模式
    * @param ignoreError 导入中忽略错误
    * @return Mono<ResponseEntity<ImportResult>>
    */
    @PreAuthorize("hasAnyAuthority('ROLE_SUPERADMIN','{{projectName}}-{{apiEntity.entity.codeName}}-Save-all')")
    @ApiOperation(value = "批量导入{{apiEntity.entity.logicName}}", tags = {"{{apiEntity.entity.logicName}}" },  notes = "批量导入{{apiEntity.entity.logicName}}")
	@PostMapping("{{pluralize apiEntity.opt.codeName}}/import")
    public Mono<ResponseEntity<ImportResult>> importData(@RequestParam(value = "config" , required = false) String config ,@RequestParam(value = "ignoreerror", required = false, defaultValue = "true") Boolean ignoreError ,@RequestBody List<{{apiEntity.defaultDto.codeName}}> dtos) {
        return  Mono.just(ResponseEntity.status(HttpStatus.OK).body({{camelCase apiEntity.entity.codeName}}Service.importData(config,ignoreError,{{camelCase apiEntity.defaultDto.codeName}}Mapping.toDomain(dtos))));
    }

    {{/eq}}
    {{#eq name "Remove"}}
    /**
    * 批量删除{{apiEntity.entity.logicName}}
    * @param ids ids
    * @return Mono<ResponseEntity<Boolean>>
    */
    @PreAuthorize("hasAnyAuthority('ROLE_SUPERADMIN','{{projectName}}-{{apiEntity.entity.codeName}}-Remove-all')")
    @ApiOperation(value = "批量删除{{apiEntity.entity.logicName}}", tags = {"{{apiEntity.entity.logicName}}" },  notes = "批量删除{{apiEntity.entity.logicName}}")
	@{{pascalCase requestMethod}}Mapping("{{pluralize apiEntity.opt.codeName}}/{{#if opt.codeName}}{{lowerCase opt.codeName}}{{/if}}batch")
    public Mono<ResponseEntity<Boolean>> removeBatch(@RequestBody List<{{apiEntity.entity.keyField.type.java}}> ids) {
        {{camelCase apiEntity.entity.codeName}}Service.remove(ids);
        return  Mono.just(ResponseEntity.status(HttpStatus.OK).body(true));
    }

    {{/eq}}
    {{/unless}}
{{/unless}}
{{/each}}
}
{{/if}}